using System.Data;
using System.Reflection;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerPrefsDataManager : BaseManager<PlayerPrefsDataManager>
{
    /// <summary>
    /// 存储数据
    /// </summary>
    /// <param name="data">数据对象</param>
    /// <param name="keyName">数据名称（唯一）</param>
    public void SaveData(object data, string keyName)
    {
        Type dataType = data.GetType(); //传入数据的类型
        //得到传进来的数据类型
        FieldInfo[] fieldInfos = dataType.GetFields(); //得到数据类型中的公共变量
        string keyNameRule;
        FieldInfo info;

        for (int i = 0; i < fieldInfos.Length; i++)
        {
            info = fieldInfos[i]; //得到对应的变量的值
            keyNameRule = keyName + "_" + dataType.Name + "_" + info.FieldType.Name + "_" + info.Name;
            SaveValue(info.GetValue(data), keyNameRule);

        }

    }
    public void SaveValue(object value, string valueName)
    {
        Debug.Log(valueName);
        Type dataType = value.GetType(); //传入数据的类型
        //value.GetType()   当前的变量类型
        if (dataType == typeof(string))
        {
            PlayerPrefs.SetString(valueName, value.ToString());
        }
        else if (dataType == typeof(int))
        {
            PlayerPrefs.SetInt(valueName, (int)value);
        }
        else if (dataType == typeof(float))
        {
            PlayerPrefs.SetFloat(valueName, (float)value);
        }
        else if (dataType == typeof(bool))
        {
            PlayerPrefs.SetInt(valueName, ((bool)value == true ? 0 : 1));
        }
        else if (typeof(IList).IsAssignableFrom(dataType))  //判断泛型类的类型  通过反射 判断 父子关系  这相当于判断字段是不是IList的子类
        {
            //父类装子类
            IList list = value as IList;
            //储存列表长度
            PlayerPrefs.SetInt(valueName, list.Count);
            int index = 0;
            foreach (object obj in list)
            {
                SaveValue(obj, valueName + index); //调用自身，遍历list中的子元素类
                ++index;
            }
        }
        else if (typeof(IDictionary).IsAssignableFrom(dataType))
        {
            IDictionary dic = value as IDictionary;
            PlayerPrefs.SetInt(valueName, dic.Count);
            int index = 0;
            foreach (object key in dic.Keys)
            {
                SaveValue(key, valueName + "_key_" + index);//存键的信息
                SaveValue(dic[key], valueName + "_value_" + index);//存键对应的值的信息
                ++index;
            }
        }
        else //自定义类型
        {
            SaveData(value, valueName);//非递归  传入的kyeName的值是唯一的 在改变 
        }


    }
    /// <summary>
    /// 读取数据
    /// </summary>
    /// <param name="type">想要读取数据的数据类型</param>
    /// <param name="keyName">数据对象的唯一key 自己控制</param>
    /// <returns></returns>
    public object LoadData(Type type, string keyName)  //使用Type 直接在方法内部动态创建对象并返回
    {
        object data = Activator.CreateInstance(type); //创建对象
        FieldInfo[] fieldInfos = type.GetFields();    //获得公共成员变量
        string keyNameRule;
        FieldInfo info;
        for (int i = 0; i < fieldInfos.Length; i++)
        {
            info = fieldInfos[i];
            keyNameRule = keyName + "_" + type.Name + "_" + info.FieldType.Name + "_" + info.Name;
            info.SetValue(data, LoadValue(info.FieldType, keyNameRule));
        }
        return data;
    }
    object LoadValue(Type type, string valueName)
    {
        if (type == typeof(System.String))
        {
            return PlayerPrefs.GetString(valueName);
        }
        else if (type == typeof(System.Int32))
        {
            return PlayerPrefs.GetInt(valueName);
        }
        else if (type == typeof(System.Single))
        {
            return PlayerPrefs.GetFloat(valueName);
        }
        else if (type == typeof(System.Boolean))
        {
            return PlayerPrefs.GetInt(valueName) == 0 ? true : false;
        }
        else if (typeof(IList).IsAssignableFrom(type))
        {
            Debug.Log("进入加载列表方法");
            //父类实现子类
            //1.从硬盘读取数据
            //列表的名字 keyNameRule  列表的长度   列表的类型 通过fieldInfos[i] 得到
            //List<Type> list = new List<Type>();
            //Debug.Log(info.FieldType);
            //Type listType = info.FieldType;
            IList list = Activator.CreateInstance(type) as IList;
            int listIndex = PlayerPrefs.GetInt(valueName);
            for (int i = 0; i < listIndex; i++)
            {
                list.Add(LoadValue(type.GetGenericArguments()[0], valueName + i));
            }
            return list;
            //info.SetValue(data, list);
            //2.将数据赋给传入的Type类实例 data
            //3.data返回出去
        }
        else if (typeof(IDictionary).IsAssignableFrom(type))
        {
            Debug.Log("进入加载字典方法");
            //1.创建一个 字典 2.获取字典的键 值 类型 3.获取键 值  的对应值 4.将键 值添加入字典中并返回字典
            IDictionary dic = Activator.CreateInstance(type) as IDictionary;
            int dicIndex = PlayerPrefs.GetInt(valueName);
            Type[] dicType = type.GetGenericArguments();

            for (int i = 0; i < dicIndex; i++)
            {
                dic.Add(LoadValue(dicType[0], valueName + "_key_" + i), LoadValue(dicType[1], valueName + "_value_" + i)); //键值
            }
            return dic;

        }
        else
        {
            return LoadData(type, valueName); 
        }
    }

}
